#include "iot/thing.h"
#include "board.h"
#include "audio_codec.h"

#include <driver/gpio.h>
#include <esp_http_client.h>
#include <esp_log.h>
#include "esp_crt_bundle.h"
#include "esp_event.h"
#include "esp_wifi.h"

#define TAG "BiliFans"
static const char *url = "https://api.bilibili.com/x/relation/stat?vmid=54916800"; // Update to use vmid

int GetFansCountFromAPI() {
    esp_http_client_config_t config = {};
    config.url = url;
    config.method = HTTP_METHOD_GET;
    config.transport_type = HTTP_TRANSPORT_OVER_TCP;
    config.crt_bundle_attach = esp_crt_bundle_attach;
    config.timeout_ms = 5000; // Explicit timeout

    esp_http_client_handle_t client = esp_http_client_init(&config);
    if (!client) {
        ESP_LOGE(TAG, "Failed to initialize HTTP client");
        return -1; // Distinct error code
    }

    // Open connection
    esp_err_t err = esp_http_client_open(client, 0);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
        esp_http_client_cleanup(client);
        return -1;
    }

    // Fetch headers
    int content_length = esp_http_client_fetch_headers(client);
    if (content_length < 0) {
        ESP_LOGE(TAG, "Failed to fetch headers");
        esp_http_client_close(client);
        esp_http_client_cleanup(client);
        return -1;
    }

    if (esp_http_client_get_status_code(client) != 200) {
        ESP_LOGE(TAG, "HTTP request failed with status: %d", esp_http_client_get_status_code(client));
        esp_http_client_close(client);
        esp_http_client_cleanup(client);
        return -1;
    }

    // Allocate response buffer
    char *response_buffer = (char*)malloc(content_length + 1);
    if (!response_buffer) {
        ESP_LOGE(TAG, "Failed to allocate memory for response");
        esp_http_client_close(client);
        esp_http_client_cleanup(client);
        return -1;
    }

    // Read response
    int total_read_len = 0;
    while (total_read_len < content_length) {
        int read_len = esp_http_client_read(client, response_buffer + total_read_len, content_length - total_read_len);
        if (read_len <= 0) {
            ESP_LOGW(TAG, "Read incomplete: %d of %d bytes", total_read_len, content_length);
            break;
        }
        total_read_len += read_len;
    }
    response_buffer[total_read_len] = '\0';
    
    // Parse JSON
    int fans_count = -1;
    cJSON *json = cJSON_Parse(response_buffer);
    if (!json) {
        ESP_LOGE(TAG, "Failed to parse JSON: %s", response_buffer);
    } else {
        cJSON *code = cJSON_GetObjectItemCaseSensitive(json, "code");
        if (code && cJSON_IsNumber(code) && code->valueint == 0) {
            cJSON *data = cJSON_GetObjectItemCaseSensitive(json, "data");
            if (data) {
                cJSON *follower = cJSON_GetObjectItemCaseSensitive(data, "follower");
                if (follower && cJSON_IsNumber(follower)) {
                    fans_count = follower->valueint;
                    ESP_LOGI(TAG, "Fans count: %d", fans_count);
                } else {
                    ESP_LOGE(TAG, "Missing or invalid 'follower' field");
                }
            } else {
                ESP_LOGE(TAG, "Missing 'data' field");
            }
        } else {
            ESP_LOGE(TAG, "Invalid API response code: %d", code ? code->valueint : -1);
        }
        cJSON_Delete(json);
    }

    // Log response for debugging
    ESP_LOGI(TAG, "Response: %s", response_buffer);

    // Cleanup
    free(response_buffer);
    esp_http_client_close(client);
    esp_http_client_cleanup(client);

    return fans_count;
}

namespace iot {

    class BiliFans : public Thing {
    private:
        esp_timer_handle_t clock_timer_handle_ = nullptr;
        int fans_count_ = 0;

        bool wifi_connected_ = false; // 标记 Wi-Fi 状态

        static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
            BiliFans* instance = static_cast<BiliFans*>(arg);
    
            if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
                ESP_LOGI("BiliFans", "Wi-Fi connected, updating fans count...");
                instance->OnWifiConnected();
            }
            if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
                ESP_LOGW("BiliFans", "Wi-Fi disconnected, pausing update timer...");
                instance->OnWifiDisconnected();
            }
        }
    
        void OnWifiConnected() {
            wifi_connected_ = true;
            UpdateFansCount();
            if (clock_timer_handle_) {
                esp_timer_start_periodic(clock_timer_handle_, 5 * 60 * 1000000);
            }
        }
    
        void OnWifiDisconnected() {
            wifi_connected_ = false;
            if (clock_timer_handle_) {
                esp_timer_stop(clock_timer_handle_);
            }
        }
    
        void UpdateFansCount() {
            fans_count_ = GetFansCountFromAPI();
            if (fans_count_ < 0) {
                ESP_LOGE(TAG, "Failed to get fans count");
            }
            ESP_LOGI(TAG, "Fans count updated: %d", fans_count_);
        }
        void InitializeEvent() {
            esp_timer_create_args_t clock_timer_args = {
                .callback = [](void* arg) {
                    BiliFans* instance = (BiliFans*)(arg);
                    instance->UpdateFansCount();
                },
                .arg = this,
                .dispatch_method = ESP_TIMER_TASK,
                .name = "BiliFansUpdateTimer",
                .skip_unhandled_events = true
            };
            esp_timer_create(&clock_timer_args, &clock_timer_handle_);
            
            ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &BiliFans::wifi_event_handler, this));
            ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &BiliFans::wifi_event_handler, this));
        }
    public:
        BiliFans() : Thing("BiliFans", "这是一个获取B站粉丝数的设备") {
            InitializeEvent();
    
            properties_.AddNumberProperty("FansCount", "当前粉丝数", [this]() -> int { return fans_count_; });
        }
        ~BiliFans() {
            if (clock_timer_handle_) {
                esp_timer_stop(clock_timer_handle_);
                esp_timer_delete(clock_timer_handle_);
                clock_timer_handle_ = nullptr;
            }
           
            esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &BiliFans::wifi_event_handler);
            esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &BiliFans::wifi_event_handler);
        }

    };

} // namespace iot

DECLARE_THING(BiliFans);
